home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / Libraries / DCLAP 4j / DNet / DTCP.cpp < prev    next >
Encoding:
Text File  |  1995-12-17  |  17.3 KB  |  884 lines  |  [TEXT/R*ch]

  1. // DTCP.cp 
  2. // by D. Gilbert, 1991-92, with help from code of Harry Chesley and others 
  3. // 1994 -- rewritten for multi-platform tcp-sockets
  4.  
  5.  
  6. #include "DTCP.h"
  7. #include <DUtil.h>
  8. #include <ncbi.h>
  9. #include <dgg.h>
  10. #include <Dversion.h>
  11.  
  12. #include "dnettcp.h"
  13.  
  14.  
  15. Local const    short        kUTCPVersion    = 3;
  16. Local const    char*        kUTCPVersionString = 
  17. #ifdef WIN_MAC
  18. "v.3.3d, Jan 95 (mac)";
  19. #endif
  20. #ifdef WIN_MSWIN
  21. "v.3.3d, Jan 95 (mswin)";
  22. #endif
  23. #ifdef WIN_MOTIF
  24. "v.3.3d, Jan 95 (xwin)";
  25. #endif
  26.  
  27.  
  28. enum tcpErrors {    
  29.     kErrConnectionBroken = -1, //common way for gopher server to end transmission 
  30.     kErrTimedOut = -2,
  31.     kErrUserBreak = -3,
  32.     kErrMemFull = -4,
  33.     kErrOpenTimeout = -5
  34.     };
  35.  
  36. Local const short        kRecvChunkSize = 500;       // bytes/ handle increment
  37. Local const    short     kTCPDefaultTimeout = 1200;    // default # ticks (1/60sec) to wait for TCP remote
  38. Local const long         kDefaultOpenDelay = 20;
  39.  
  40.         // this is a guess -- no generic way to find memory available
  41. Local const    long    kMaxReadBuffer = 4048; //32000;
  42.                         
  43.  
  44.  
  45.     // Public Global vars
  46. Global long        gTCPTimeout = kTCPDefaultTimeout;
  47.  
  48. Local short     gMacTCPRefNum = 0;        // not a global now...
  49.  
  50.     // Private global vars
  51. Local long      gMyIP = 0;
  52. Local char*         gMyDotName = NULL; 
  53. Local Boolean gResolverIsOpen = false;
  54.  
  55.  
  56.  
  57.  
  58. short OpenMacTCP()
  59. {
  60.     if (gMacTCPRefNum !=0 ) 
  61.         return 0;
  62.     else {
  63.         short err= 0;
  64.         return err;
  65.         }
  66. }
  67.  
  68. void InitializeTCP()         // InitUMacTCP()
  69. {
  70.     gMyDotName = NULL;
  71.     gMacTCPRefNum= 0;
  72.     short err= OpenMacTCP(); 
  73. }
  74.  
  75. void FinishTCP()                 // CloseDownUMacTCP()
  76. {
  77.     gMacTCPRefNum = 0;
  78. }
  79.  
  80. Boolean TCPIsItInstalled()         // IsMacTCPInstalled()
  81. {
  82.     return (0 == OpenMacTCP());
  83. }
  84.  
  85. long MyIP()
  86. {
  87.     if (!OpenMacTCP() || gMyIP)  return gMyIP;
  88.     gMyIP = MyIPaddress();
  89.     return gMyIP;
  90. }
  91.  
  92. void GetMyDotName(char* myDotName)
  93. {
  94.     if (!OpenMacTCP()) {
  95.         myDotName = gMyDotName = ".";
  96.         return;
  97.         }
  98.     if (myDotName) gMyDotName= IP2DotName(MyIP());
  99.     myDotName = gMyDotName;
  100. }    
  101.  
  102.  
  103. char* IP2DotName(long ip)
  104. {
  105.     char *name = NULL;
  106.     
  107.     // ?? do we need this proc
  108.     return name;
  109. }
  110.  
  111.  
  112. long DotName2IP(const char* name)
  113. {
  114.     return Hostname2IP( (char*)name);
  115. }
  116.  
  117.  
  118.  
  119.  
  120. // DTCP ..........................
  121.  
  122. void DTCP::Initialize()
  123. {
  124.     fSocket= -1;
  125.     fError= NULL;
  126.     fErrNo= 0;
  127.     fFailed= false;
  128.     fTimeout= gTCPTimeout;
  129.     fLastSentCRLF= false;
  130.     
  131.     fDoShowProgress= false;
  132.     fResultSize= 0;
  133.     fMaxResultSize= 0;
  134.     fResultNew= 0;
  135.     fBytesread= 0;
  136.     fResultTotal= 0; // this is now a ShowProgress::LastBytesRead counter
  137.     fLimitResultSize= 0;
  138.     fEndofMessage= false;
  139.     fResultHand= NULL;
  140.     fNullTerm= true; //??
  141.     fLastc = fLast2c= fLast3c = 0; // receive -- CRLF conversion record
  142.     fStartTime= 0;
  143.     fConnectTime= 0;
  144.  
  145.     fMessageProc = NULL;
  146.     fMessageObj = NULL;
  147.     fBreakProc = NULL;
  148.     fBreakObj = NULL;
  149.     fReadSaveLen = 0;
  150.     fReadSaveBase = NULL;
  151.     fReadSave = NULL;
  152.  
  153.     (void) OpenMacTCP();
  154. }
  155.  
  156.  
  157. DTCP::DTCP()
  158. {
  159.     Initialize();
  160. }
  161.  
  162.  
  163. DTCP::~DTCP() 
  164. {
  165.     if (fConnectionIsOpen)  
  166.         Close();
  167.     if (fStreamIsOpen)  
  168.         Release();
  169. }
  170.  
  171.  
  172. Boolean DTCP::UserBreak()
  173. {  
  174.     if (fBreakProc)
  175.         return (fBreakProc)(fBreakObj);
  176.     else
  177.         return false;
  178. }    
  179.  
  180. void DTCP::StreamYieldTime()
  181. {
  182.     if (UserBreak()) Fail(-1); //??
  183. }
  184.  
  185.  
  186. void DTCP::Fail(long errNo)
  187. {
  188.     if (errNo) {
  189.         fErrNo= errNo;
  190.         fError= NULL;
  191.         fFailed= true;
  192.         Nlm_Message (MSG_ERROR, "Network DTCP error # %d",errNo);
  193.         }
  194. }
  195.  
  196.  
  197. void DTCP::Fail(const char* msg)
  198. {
  199.     if (msg) {
  200.         fErrNo= 0;
  201.         fError= (char*) msg;
  202.         fFailed= true;
  203.         Nlm_Message (MSG_ERROR, "Network DTCP error: %s", (char*) msg);
  204.         }
  205. }
  206.  
  207. Boolean DTCP::Failed()
  208. {
  209.     return fFailed;
  210. }
  211.  
  212.  
  213.  
  214. void DTCP::InstallUserBreak(TCPUserBreakHandler aproc, DTaskMaster* itsObject)
  215. {
  216.     fBreakProc= aproc;
  217.     fBreakObj= itsObject;
  218. }
  219.  
  220. void DTCP::InstallMessageHandler(TCPMessageHandler aproc, DTaskMaster* itsObject)
  221. {
  222.     fMessageProc= aproc;
  223.     fMessageObj= itsObject;
  224. }
  225.  
  226. void DTCP::ShowMessage(const char* msg)
  227. {
  228.     if (fMessageProc) (fMessageProc)(fMessageObj, 0, msg);
  229. }
  230.  
  231. Boolean DTCP::IsTCPInstalled()
  232. {
  233.     return TCPIsItInstalled();
  234. }
  235.  
  236.  
  237. long DTCP::NameToAddress(const char* hostName)
  238. {
  239.     return DotName2IP(hostName);
  240. }
  241.  
  242.     // non-functional IP2DotName...
  243. char* DTCP::AddressToName(long address)
  244. {
  245.     return IP2DotName(address);
  246. }
  247.  
  248.     // non-functional IP2DotName...
  249. char* DTCP::DotAddrToName(const char* dotAddress)
  250. {
  251.     return IP2DotName( DotName2IP( dotAddress));
  252. }
  253.  
  254. char* DTCP::RemoteName()
  255. {
  256.     char* name = NULL;
  257.     if (fSocket>=0) {
  258.         const long namelen = 256;
  259.         name= (char*) MemNew(namelen);
  260.         short err= SockHostname(fSocket, name, namelen);
  261.         }
  262.     return name;
  263. }
  264.  
  265.  
  266.         // do we want both of these??
  267. long DTCP::Version()
  268. {
  269. #if 1
  270.     return kDCLAPVersion;
  271. #else
  272.     return kUTCPVersion;
  273. #endif
  274. }
  275.  
  276. const char* DTCP::VersionString()
  277. {
  278. #if 1
  279.     return kDCLAPVersionString;
  280. #else
  281.     return kUTCPVersionString;
  282. #endif
  283. }
  284.  
  285.  
  286. char* DTCP::StatusString(short state)
  287. {
  288.     switch (state) {
  289.         case kTCPlistening    : return "TCP listening";
  290.         case kTCPwaitingforopen: return "TCP waiting for open";
  291.         case kTCPopening        : return "TCP opening";
  292.          case kTCPestablished: return "TCP established";
  293.         case kTCPPleaseClose: return "TCP please close";
  294.         case kTCPclosing        : return "TCP closing";
  295.         case kTCPclosed            : return "TCP closed";
  296.         case kTCPreleased        : return "TCP released";
  297.         case kTCPUnknownState:
  298.         default                            : return "TCP unknown state";
  299.         }
  300. }
  301.  
  302.  
  303. long DTCP::Status()
  304. {
  305.     if (!fStreamIsOpen)                return kTCPreleased;
  306.     else if (!fConnectionIsOpen)     return kTCPPleaseClose;
  307.     else                                          return kTCPestablished;
  308. }
  309.  
  310. void DTCP::StatusMessage(void)
  311. {
  312.     ShowMessage( StatusString(Status()));
  313. }
  314.  
  315. Boolean DTCP::EndOfMessage()
  316. {
  317.     return fEndofMessage;
  318.     //?? return (fEndofMessage || (NewBytesReceived == 0));
  319.     //^^ bad when linefeeds are received but don't count in NewBytesRec...!!!
  320. }
  321.  
  322. void DTCP::SetEndOfMessage( Boolean isEnded)
  323. {
  324.     fEndofMessage= isEnded;
  325. }
  326.  
  327.  
  328. //ncbi.h:     time_t Nlm_GetSecs() == time() call, should be okay on all ansi c systems?
  329.  
  330. Boolean DTCP::WaitedForOpen(long delayticks)
  331. {
  332.     short        currStat, oldStat;
  333.     
  334.     oldStat= -123;
  335.     while (true) {
  336.         // Delay(5, &aTicks); << what is ncbi/generic equivalent ??
  337.         //for (aTicks= GetSecs() + 5; GetSecs() < aTicks; ) ;
  338.         
  339.         currStat= (short)Status();
  340.         if (currStat!=oldStat) ShowMessage( StatusString(currStat));
  341.         switch (currStat) {
  342.         
  343.             case kTCPestablished:  
  344. #if FIX_LATER
  345.                 //if (delayticks) 
  346.                 //for (aTicks= GetSecs() + delayticks; GetSecs() < aTicks; ) ;
  347.                 // ^^ this is TOO LONG
  348. #endif
  349.                 return true;
  350.  
  351.             case kTCPUnknownState:
  352.             case kTCPPleaseClose:
  353.             case kTCPreleased:
  354.             case kTCPclosed    :  
  355.                 Fail("Couldn't connect to TCP service.");
  356.                 Release();
  357.                 return false;
  358.                 
  359.             default: if (UserBreak()) {
  360.                 Release();
  361.                 return false;
  362.                 }
  363.             }
  364.         oldStat= currStat;
  365.         }
  366.     return false;
  367. }
  368.  
  369. Boolean DTCP::WaitedForOpen()
  370. {
  371.     return WaitedForOpen(kDefaultOpenDelay);
  372. }
  373.  
  374.  
  375.  
  376. void DTCP::SetShowProgress( Boolean turnOn)
  377. {
  378.     fDoShowProgress= turnOn;
  379. }
  380.  
  381. void DTCP::ShowProgress( long sendRecvCount)
  382. {
  383.     char msg[128];
  384.     sprintf( msg, "TCP bytes sent: %d", sendRecvCount);
  385.     ShowMessage(msg);
  386. }
  387.  
  388. void DTCP::ShowProgress()
  389. {
  390.     if (fBytesread > fResultTotal + 1024) {
  391.         ShowProgress( fBytesread);
  392.         fResultTotal= fBytesread;
  393.         }
  394. }
  395.  
  396.  
  397.  
  398.  
  399. void DTCP::Release()
  400. {
  401.     short err;
  402.     fBytesread= 0;
  403.     fStreamIsOpen = false;
  404.     if (fSocket>=0) err= SockClose(fSocket); 
  405.     fSocket= -1;
  406.     fConnectionIsOpen = false;
  407. }
  408.  
  409.  
  410.  
  411. void DTCP::Open( char* hostname, unsigned short hostport, unsigned short localport)
  412. {
  413.     fBytesread= 0;
  414.     fLastc= fLast2c= fLast3c= 0;
  415.     fConnectTime= 0;
  416.     fStartTime=    GetSecs();
  417.     fLastSentCRLF= false;
  418.     fConnectionIsOpen= false;
  419.     
  420.     fSocket= SockOpen( hostname, hostport);
  421.     if (fSocket<0) switch (fSocket) {
  422.         case errHost        :    Fail("Can't resolve host name"); return;
  423.         case errSocket    : Fail("Can't create IP socket"); return;
  424.         case errConnect    : Fail("Can't connect to host");    return;
  425.         default                    : Fail("Can't open IP connection"); return;
  426.         }
  427.     fStreamIsOpen = true;
  428.     fConnectionIsOpen = true;
  429. }
  430.  
  431.  
  432.  
  433. // CloseConnection aborts the connection if it could not be closed
  434. void DTCP::Close()
  435. {
  436.     short err;
  437.     fConnectTime = GetSecs() - fStartTime;
  438.     if (fSocket>=0)  err= SockClose(fSocket); 
  439.     fSocket= -1;
  440.     fConnectionIsOpen = false;
  441. }
  442.  
  443.  
  444. void DTCP::Abort()
  445. {
  446.     short err;
  447.     if (fSocket>=0) err= SockClose(fSocket); 
  448.     fSocket= -1;
  449.     fConnectionIsOpen = false;
  450. }
  451.  
  452.  
  453.  
  454.  
  455.  
  456. // Send functions ......................................
  457.  
  458.  
  459. void DTCP::SendBytes(void *data, long datasize, Boolean immediately)
  460. {
  461.     long len= SockWrite( fSocket, data, datasize);
  462.     char*    pp =  (char*) data;
  463.     fLastSentCRLF= (pp[datasize-1] == kLF && pp[datasize-2] == kCR);
  464. }
  465.  
  466.  
  467. void DTCP::Send( char* cstring, Boolean immediately)
  468. {
  469.     SendBytes( cstring, StrLen(cstring), immediately);
  470. }
  471.  
  472. void DTCP::SendCRLF(Boolean EvenIfLastSendHadCRLF, Boolean immediately)
  473. {
  474.     static char    buf[2] = {kCR,kLF};
  475.     if (EvenIfLastSendHadCRLF || !fLastSentCRLF)
  476.         SendBytes( &buf, 2, immediately);
  477. }
  478.  
  479. void DTCP::SendStr( char* s, Boolean addCRLF, Boolean immediately)
  480. {
  481.     SendBytes( s, strlen(s), immediately);
  482.     if (addCRLF)    SendCRLF( true, immediately);
  483. }
  484.  
  485.  
  486.  
  487.  
  488.  
  489.  
  490.  
  491.  
  492. // Receive status functions ......................................
  493.  
  494. long DTCP::CharsAvailable() 
  495. {        
  496.     if (!fStreamIsOpen) 
  497.         return 0;
  498.     else if (!fConnectionIsOpen)  
  499.         return 0;
  500.     else {
  501.         long charsleft =  0;
  502.         
  503.         if (fReadSave) charsleft= fReadSaveLen;
  504.         
  505.             // ?? how do we deal w/ this in sockets ??
  506.             // do we need to use select(n, readfds, writefds, errfds, timeout);
  507.             // doesn't select() set a file descripttor for async operations??
  508. #if 0
  509.         long readarray[1] = { fSocket };
  510.         long maxtime = 1;
  511.         short result= SockSelect( 1, readarray, NULL, NULL, maxtime);
  512.         if (result > 0) charsleft++; // don't know how many...
  513. #endif
  514.  
  515.         return charsleft;
  516.         }
  517. }
  518.  
  519. void DTCP::EatResponseLine(void)
  520. {
  521.     long bytesread;
  522.     (void) MemFree( RecvLine()); // hanging up here !!?? in sendmail
  523.     (void) MemFree( RecvChars( CharsAvailable(), bytesread ));    
  524. }
  525.  
  526.  
  527. long DTCP::TotalBytesReceived()
  528. // total over life of the DTCP (since init), or multiple calls to RecvUpTo, RecvChunk ...
  529. {
  530.     return fBytesread; // fResultTotal;
  531. }
  532.  
  533. long DTCP::NewBytesReceived()
  534. // total only for last read 
  535. {
  536.     return fResultNew;
  537. }
  538.  
  539. void DTCP::NullTerm( Boolean turnon)
  540. {
  541.     fNullTerm = turnon;
  542. }
  543.  
  544. long DTCP::ConnectTime()
  545. {
  546.     if (fConnectionIsOpen) fConnectTime = GetSecs() - fStartTime;
  547.     return fConnectTime;
  548. }
  549.  
  550.  
  551.  
  552.  
  553. // Receive functions ......................................
  554.  
  555.  
  556. short DTCP::ReceiveData(void *data, long datasize, long &bytesReceived, Boolean stopatlf)
  557. {
  558.     short    err= 0;
  559.     long startTick= GetSecs();
  560.     long oldBytes = fBytesread;
  561.     Boolean done    = datasize < 1;
  562.     bytesReceived = 0;
  563.     char*    datap        = (char*) data;
  564.         
  565.     long count;
  566.     
  567.     if (fReadSave) {
  568.         // read from local buffer...
  569.         count= Min( datasize, fReadSaveLen);
  570.         if (stopatlf) {
  571.             char* lfp= (char*) MemChr( fReadSave, kLF, count);
  572.             if (lfp) { 
  573.                 count= lfp - fReadSave + 1;
  574.                 done= true;
  575.                 }
  576.             }
  577.         MemCpy( datap, fReadSave, count);
  578.         datap += count;
  579.         bytesReceived += count;
  580.         datasize -= count;
  581.         if (datasize<1) done= true;
  582.         fReadSaveLen -= count;
  583.         if (fReadSaveLen > 0) {
  584.             fReadSave += count; // just push up pointer... keep fReadSaveBase around
  585.             }
  586.         else {
  587.             fReadSaveBase= (char*) MemFree( fReadSaveBase);
  588.             fReadSave= fReadSaveBase;
  589.             fReadSaveLen= 0;
  590.             }
  591.         }
  592.  
  593.     while ( !done ) {
  594.         count= SockRead( fSocket, datap, datasize);
  595.       if (count > 0) {
  596.       
  597.             if (stopatlf) {
  598.                 char *lfp= (char*) MemChr(datap, kLF, count);
  599.                 if (lfp) {
  600.                     long newcount= lfp - datap + 1;
  601.                     if (newcount < count) {
  602.                         fReadSaveLen= count - newcount;
  603.                         fReadSaveBase=    (char*) MemDup( lfp+1, fReadSaveLen);
  604.                         fReadSave= fReadSaveBase;
  605.                         count= newcount;
  606.                         }
  607.                     done= true;
  608.                     }
  609.                 }
  610.                 
  611.             datap     += count;
  612.             bytesReceived += count;
  613.             datasize -= count;
  614.             if (datasize<1) done= true;
  615.             }
  616.         else {
  617.             done= true; 
  618.             if (count < 0) { err= count; fEndofMessage= true; } //??
  619.             else if (count == 0) fEndofMessage= true; // !! need this for unix/win_motif
  620.             }
  621.         }
  622.     
  623.     fBytesread= oldBytes + bytesReceived;
  624.         
  625.     StreamYieldTime();
  626.     return err;
  627. }
  628.  
  629.  
  630.  
  631.  
  632.  
  633.         //     CAN'T RELY ON NULL TERMINATED STRINGS w/ BINARY DATA !!!
  634.             
  635.     
  636. char* DTCP::ReadWithChecks( 
  637.                         long& bufsize,
  638.                         long     expectedbytes/* = kTCPStopAtclose*/, 
  639.                         Boolean convertnewline/* = false*/, 
  640.                         long     maxbytes/* = 0*/, 
  641.                         char* oldbuffer/* = NULL*/)
  642. {
  643.     long    bytesread = 0, bufadditions = 0, newbytes= 0;
  644.     long     oldbytes= fBytesread;
  645.     Boolean stopAtdotcrlf = (expectedbytes == kTCPStopAtdotcrlf);
  646.     Boolean done = false;
  647.     short    err = 0;
  648.     long     count, newcount;
  649.     char* bufat;
  650.     long     startTick = GetSecs();
  651.  
  652.     if (maxbytes <= 0) maxbytes= kMaxReadBuffer;
  653.     else maxbytes= Min(maxbytes, kMaxReadBuffer);
  654.     fResultNew= 0; //??
  655.  
  656.     if (oldbuffer == NULL) { 
  657.         bufsize= 0; 
  658.         oldbuffer= (char*) MemGet(1, true);
  659.         }
  660.     else {
  661.         // --- NOW, assume caller passes true size of oldbuffer -- for data w/ nulls
  662.         //bufsize= strlen(oldbuffer); // <<!!! Implies null term !!!
  663.       //if (bufsize && oldbuffer[bufsize-1] == 0) bufsize--;
  664.         }
  665.         
  666.     gErrorManager->TurnOff();        
  667.     do {
  668.         count= maxbytes - newbytes; 
  669.         if (count>0) {
  670.             bufat= (char*) MemMore( oldbuffer, bufsize + count + 1);
  671.             if (bufat) oldbuffer= bufat;
  672.             else { 
  673.                 fResultNew= -1; // flag for out-of-mem
  674.                 goto finish;         // out of mem
  675.                 }
  676.             bufat= oldbuffer + bufsize;
  677.             newcount = 0;
  678.  
  679.             err= ReceiveData( bufat, count, newcount, stopAtdotcrlf);
  680.             
  681.             if (newcount>0 && stopAtdotcrlf) {
  682.                 if (bufat[0] == '.' && (bufat[1] == kCR || bufat[1] == kLF)) {
  683.                     newcount= 0;
  684.                     fEndofMessage= true;
  685.                     }
  686.                 } 
  687.             count= newcount;
  688.             
  689.             bufsize  += count;
  690.             newbytes += count;
  691.             StreamYieldTime();
  692.             }
  693.     } while (err == 0 && count > 0);
  694.     fResultNew = newbytes;
  695.         
  696. finish:
  697.     gErrorManager->TurnOn();        
  698.     
  699.     if (convertnewline && bufsize) { 
  700.         // ?? this is screwy -- some texts have all cr stripped, some have extras !!
  701.         if (LineEndSize == 2) { // what the net lineend is
  702.             if (LineEnd[0] == kCR && LineEnd[1] == kLF) ;
  703.             else ; // convert CRLF to LineEnd
  704.             }
  705.             
  706.         else if (LineEndSize == 1) {
  707.             char *from= oldbuffer;
  708.             char *tob= oldbuffer;
  709.  
  710.             if (*LineEnd == kLF) {
  711.                 for (count= 0; count<bufsize; count++, from++) {
  712.                     if (*from != kCR) 
  713.                         *tob++= *from;
  714.                   else if (from[1] != kLF) 
  715.                       *tob++= kLF;  // fails at count==bufsize-1
  716.                   }
  717.                 }
  718.                 
  719.             else if (*LineEnd == kCR) {
  720.                 for (count= 0; count<bufsize; count++, from++) {
  721.                     if (*from != kLF) 
  722.                         *tob++= *from;
  723.                   else if (from[-1] != kCR) 
  724.                       *tob++= kCR;   
  725.                   }
  726.                 }
  727.  
  728.             *tob= 0;
  729.             bufsize= tob - oldbuffer; 
  730.             }
  731.         }    
  732.         
  733.             // shrink it down to bufsize..
  734.     oldbuffer= (char*) MemMore( oldbuffer, bufsize + 1);
  735.     if (true) { //fNullTerm !!!
  736.         oldbuffer[bufsize] = '\0'; // always now, no such GetPtrSize(p) for generic systems
  737.         }
  738.  
  739.     if (err != 0)  {
  740. #if FIX_LATER
  741.         fEndofMessage= (Status() != kTCPestablished);
  742. #else
  743.         fEndofMessage= true;
  744. #endif
  745.         }
  746.         
  747.     return oldbuffer;
  748. }
  749.  
  750.  
  751.  
  752.  
  753. short DTCP::RecvByte()
  754. {
  755.     unsigned char b;
  756.     long bytesread= 0;
  757.     short err= ReceiveData( &b, 1, bytesread);
  758.     if (bytesread>0) return b; 
  759.     else return -1;            
  760. }
  761.  
  762.  
  763. char* DTCP::RecvLine() // read up to kLF 
  764. {
  765.     const    short    kBufSize = 511;
  766.     char    buf[kBufSize+1];
  767.      short    err= 0;
  768.      
  769.     if (!fConnectionIsOpen) return false;
  770.     fResultSize= 0;
  771.     fMaxResultSize= 0;
  772.     fResultNew= fResultSize;  //save for close calculation
  773.     fEndofMessage= false;
  774.  
  775.     long     bytesread = 0;
  776.     err= ReceiveData( buf, kBufSize, bytesread, true);
  777.     if (bytesread > 0) {
  778.         fResultSize += bytesread;
  779.         fResultNew = fResultSize;
  780.         buf[bytesread]= 0;
  781.         return (char*)MemDup(buf,bytesread+1);
  782.         }
  783.     else
  784.         return NULL;
  785. }
  786.  
  787.  
  788.   
  789. char* DTCP::RecvChars(long readCount, long& numread)
  790.     long  thisread;
  791.     long  bufsize= readCount;
  792.     short err= 0;
  793.     
  794.     numread = 0;
  795.     if (!fConnectionIsOpen) return NULL; 
  796.     gErrorManager->TurnOff();        
  797.     fResultHand= (char*) MemNew(bufsize+1);
  798.     gErrorManager->TurnOn();
  799.     if (!fResultHand) 
  800.         return NULL;
  801.         
  802.     char* p= fResultHand;
  803.     if (readCount > 0) do {
  804.         thisread= 0;
  805.         err= ReceiveData( p, bufsize, thisread);
  806.         p += thisread;
  807.         bufsize -= thisread;
  808.         numread += thisread;
  809.     } while (thisread > 0 && bufsize > 0);
  810.         
  811.     if (true) { //fNullTerm)
  812.         fResultHand[numread] = '\0';
  813.         }
  814.     return fResultHand;
  815. }
  816.  
  817.  
  818. #if FIX_MAYBE_LATER_OR_TRASH
  819.  
  820. char* DTCP::RecvChunk( long maxChunk, char* oldChunk)
  821. {    
  822.     Boolean done; 
  823.     short err= 0;
  824.     long    thisread, count, oldchunksize, newchunksize= 0;
  825.      // note: maxChunk >= newchunksize, oldchunksize is separate
  826.     
  827.     fResultNew= 0;
  828.     fResultHand= oldChunk;
  829.     if (!fConnectionIsOpen) return oldChunk;
  830.     
  831.     if (maxChunk <= 0) 
  832.         maxChunk = kMaxReadBuffer; //maxChunk= FreeMem() - (FreeMem() / 5); 
  833.     
  834.     if (oldChunk == NULL) { 
  835.         oldchunksize= 0; 
  836.         oldChunk= (char*) MemNew(oldchunksize+1);
  837.         oldChunk[oldchunksize]= '\0';        
  838.         }
  839.     else 
  840.         oldchunksize= strlen( oldChunk); // !! this implies NULL termination for all data !
  841.  
  842.     gErrorManager->TurnOff();        
  843.     do {
  844.         //count= CharsAvailable();
  845.         //if (count+newchunksize > maxChunk) count= maxChunk-newchunksize;
  846.         count= maxChunk - newchunksize;
  847.         if (count>0) {
  848.             
  849.             char* p= (char*) MemMore( oldChunk, oldchunksize + newchunksize + count + 1);
  850.             if (p) oldChunk= p;
  851.             else { // out of memory...
  852.                 fResultNew= -1;
  853.                 goto finish;
  854.                 }
  855.             p= oldChunk + oldchunksize + newchunksize;
  856.             thisread = 0;
  857.             err= ReceiveData( p, count, thisread);
  858.             newchunksize += thisread;
  859.             }
  860.  
  861.         fEndofMessage= (Status() != kTCPestablished);
  862.         if (fDoShowProgress) ShowProgress(); 
  863.         done= (err != 0 || newchunksize >= maxChunk || thisread < 1);
  864.         if (UserBreak()) {
  865.             done= true;
  866.             Fail("User break");  // ?? fail or proceed w/ short read?
  867.             }
  868.     } while (!(done || fEndofMessage));     
  869.     fResultNew= newchunksize;
  870.     
  871. finish:
  872.     gErrorManager->TurnOn();        
  873.  
  874.     if (true) { //fNullTerm) 
  875.         oldChunk[oldchunksize + newchunksize] = '\0';
  876.         }
  877.     fResultHand= oldChunk;
  878.     return oldChunk;
  879. }
  880.  
  881. #endif
  882.  
  883.